﻿using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using BenchmarkDotNet.Attributes;
using Devonline.Core;
using Devonline.Security;

namespace Security;

[SimpleJob]
[MemoryDiagnoser]
public class DataSecurity(string path)
{
    private readonly ISecurityService _securityService = new DataSecurityService(new SecuritySetting
    {
        Certificate = X509Certificate2.CreateFromPemFile(path + "rsa.pem", path + "rsa.key")
    });

    private readonly SM2SecurityService _sm2SecurityService = new SM2SecurityService(new SecuritySetting());

    [Benchmark]
    public async Task RunAsync()
    {
        var data = BitConverter.GetBytes(KeyGenerator.GetKey());
        var encrypted = await _securityService.EncryptAsync(data);
        var decrypted = await _securityService.DecryptAsync(encrypted);
        Debug.Assert(data.SequenceEqual(decrypted), "解密后未还原数据!");
    }
    [Benchmark]
    public async Task RunStringAsync()
    {
        var text = Convert.ToBase64String(BitConverter.GetBytes(KeyGenerator.GetKey()));
        var ciphertext = await _securityService.EncryptAsync(text);
        var decrypted = await _securityService.DecryptAsync(ciphertext);
        Debug.Assert(text.Equals(decrypted), "解密后未还原数据!");
    }

    [Benchmark]
    public void RunSM2()
    {
        var data = BitConverter.GetBytes(KeyGenerator.GetKey());
        _sm2SecurityService.Generate(out byte[] privateKey, out byte[] publicKey);
        var encrypted = _sm2SecurityService.Encrypt(publicKey, data);
        var decrypted = _sm2SecurityService.Decrypt(privateKey, encrypted);
        Debug.Assert(data.SequenceEqual(decrypted), "解密后未还原数据!");
    }

    /// <summary>
    /// 循环执行 Run 方法
    /// </summary>
    /// <param name="count">执行次数</param>
    /// <returns></returns>
    public async Task LoopRunAsync(int count)
    {
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} will loop run {nameof(RunAsync)} {count} times!");
        var startTime = DateTime.Now;
        for (int i = 0; i < count; i++)
        {
            await RunAsync();
        }

        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} loop run {nameof(RunAsync)}: " + startTime.GetTimeDetail());
    }
    /// <summary>
    /// 循环执行 RunString 方法
    /// </summary>
    /// <param name="count">执行次数</param>
    /// <returns></returns>
    public async Task LoopRunStringAsync(int count)
    {
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} will loop run {nameof(RunStringAsync)} {count} times!");
        var startTime = DateTime.Now;
        for (int i = 0; i < count; i++)
        {
            await RunStringAsync();
        }

        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} loop run {nameof(RunStringAsync)}: " + startTime.GetTimeDetail());
    }

    /// <summary>
    /// 并发执行 Run 方法
    /// </summary>
    /// <param name="count">执行次数</param>
    /// <returns></returns>
    public async Task ParallelRunAsync(int count)
    {
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} will parallel run {nameof(RunAsync)} {count} times!");
        var startTime = DateTime.Now;
        await Parallel.ForAsync(0, count, async (x, y) => await RunAsync());
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} parallel run {nameof(RunAsync)}: " + startTime.GetTimeDetail());
        await Task.CompletedTask;
    }
    /// <summary>
    /// 并发执行 RunString 方法
    /// </summary>
    /// <param name="count">执行次数</param>
    /// <returns></returns>
    public async Task ParallelRunStringAsync(int count)
    {
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} will parallel run {nameof(RunStringAsync)} {count} times!");
        var startTime = DateTime.Now;
        await Parallel.ForAsync(0, count, async (x, y) => await RunStringAsync());
        Console.WriteLine($"the benchmark of {nameof(DataSecurity)} parallel run {nameof(RunStringAsync)}: " + startTime.GetTimeDetail());
        await Task.CompletedTask;
    }
}